from django.test.client import RequestFactory
from graphene.types import BigInt
from graphene_django.settings import graphene_settings
from graphql import execute, parse

from nautobot.extras.models import GraphQLQuery


def execute_query(query, variables=None, request=None, user=None):
    """Execute a query from the ORM.

    Args:
        query (str): String with GraphQL query.
        variables (dict, optional): If the query has variables they need to be passed in as a dictionary.
        request (django.test.client.RequestFactory, optional): Used to authenticate.
        user (django.contrib.auth.models.User, optional): Used to authenticate.

    Returns:
        (GraphQLDocument): Result for query
    """
    if not request and not user:
        raise ValueError("Either request or username should be provided")
    if not request:
        request = RequestFactory().post("/graphql/")
        request.user = user
    schema = graphene_settings.SCHEMA.graphql_schema
    document = parse(query)
    if variables:
        return execute(schema=schema, document=document, context_value=request, variable_values=variables)
    else:
        return execute(schema=schema, document=document, context_value=request)


def execute_saved_query(saved_query_name, **kwargs):
    """Execute saved query from the ORM.

    Args:
        saved_query_name (str): Name of a saved GraphQL query.

    Keyword Args:
        variables (Optional[dict]): If the query has variables they need to be passed in as a dictionary.
        request (Optional[django.test.client.RequestFactory]): Used to authenticate.
        user (Optional[django.contrib.auth.models.User]): Used to authenticate.

    Returns:
        (GraphQLDocument): Result for query
    """
    query = GraphQLQuery.objects.get(name=saved_query_name)
    return execute_query(query=query.query, **kwargs)


class BigInteger(BigInt):
    """For backwards compatibility only."""
